package com.gbl.commands;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.util.Scanner;

import com.gbl.commands.signals.ExitCommandSignal;
import com.gbl.commands.signals.StopCommandSignal;
import com.gbl.sessions.Session;
import com.gbl.utils.Show;

/**
 * a motherclass which defines Command-like classes behaviour and methods
 * @author Guillaume Barthelemy
 *
 */
public abstract class Commands
{
	protected Session session;
	protected PrintWriter out;
	protected BufferedReader in;
	protected Scanner sc;
	
	public Commands(Session _session)
	{
		this.session = _session;
		this.out = _session.getOut();
		this.in = _session.getIn();
		this.sc = _session.getSc();
	}
	
/**
 *
 * Return whether a string is a command or not, and execute some predefined protocols if it is
 * @param str a String
 * @return a boolean whether str is a command or not
 * @throws ExitCommandSignal a signal raised when use 'Exit' command
 * @throws StopCommandSignal a signal raised when use 'Stop' command
 */
	public boolean executeCmd(String str) throws ExitCommandSignal, StopCommandSignal
	{
		if(isCommand(str))
		{
			if(str.equals(Command.HELP.toString()))
			{
				Show.test("executeCmd: case Help|str: "+str+", Command: "+Command.HELP,2);	//TEST
				doCaseHelp(str);
				return true;
			}	
			else if(str.equals(Command.MIRROR.toString()))
			{
				Show.test("executeCmd: case Mirror|str: "+str+", Command: "+Command.MIRROR,2);	//TEST
				doCaseMirror(str);
				return true;
			}
			else if(str.equals(Command.SEND.toString()))
			{
				Show.test("executeCmd: case Send|str: "+str+", Command: "+Command.SEND,2);	//TEST
				doCaseSend(str);
				return true;	
			}
			else if(str.equals(Command.STOP.toString()))
			{
				Show.test("executeCmd: case Stop|str: "+str+", Command: "+Command.STOP,2);	//TEST
				doCaseStop(str);
				throw new StopCommandSignal();	
			}
			else if(str.equals(Command.QUIT.toString()))
			{
				Show.test("executeCmd: case Quit|str: "+str+", Command: "+Command.QUIT,2);	//TEST
				doCaseExit(str);
				throw new ExitCommandSignal();	
			}
			else
			{
				Show.error("Commands.executeCmd","case default-no command");	//TEST
				return false;
			}
		}
		Show.test("Commands.executeCmd: isCommand=false",1);	//TEST
		return false;
	}	
	
	/**
	 * returns whether a string is a command or not
	 * @param str a String
	 * @return a boolean
	 */
	public static boolean isCommand(String str)
	{
		for(Command cmd : Command.values())
		{
			Show.test("isCommand: values: "+cmd.toString(),3);	//TEST
			if(cmd.toString().equals(str))
			{
				Show.test("isCommand: case true",3);	//TEST
				return true;
			}
		}
		Show.test("isCommand: case false",3);	//TEST
		return false;
	}
	
	public enum Command
	{
		HELP ("/help"),
		MIRROR ("/mirror"),
		SEND ("/send"),
		STOP ("/stop"),
		QUIT ("/quit");
		
		private String cmd = "";
		
		Command(String _cmd)
		{
			this.cmd = _cmd;
		}
		
		public String toString()
		{
			return this.cmd;
		}
	}
	
	protected void doCaseHelp(String str)
	{
		Show.trace("#-----------------------------------------------------------------------#");
		Show.trace("#--                     --  COMMAND LIST  --                          --#");
		Show.trace("#-----------------------------------------------------------------------#");
		Show.trace("# /help: the list of commands                                           #");
		Show.trace("# /send: send message to the serveur or another client and get response #");
		Show.trace("# /stop: go back to default exchange message                            #");
		Show.trace("# /mirror: same as '/send' but only get the same message as a response  #");
		Show.trace("# /quit: the list of commands                                           #");
		Show.trace("#-----------------------------------------------------------------------#");
	}
	
	protected void doCaseMirror(String str)
	{
		Show.test("doCaseMirror >> need polymorphic method from an herited class",3);
	}
	
	protected void doCaseSend(String str)
	{
		Show.test("doCaseMirror >> need polymorphic method from an herited class",3);
	}
	
	protected void doCaseStop(String str)
	{
		Show.test("doCaseStop >> need polymorphic method from an herited class",3);
	}
	
	protected void doCaseExit(String str)
	{
		Show.test("doCaseExit >> need polymorphic method from an herited class",3);
	}
}
